package org.destinyshine.cricket.container;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.destinyshine.cricket.connector.Connection;
import org.destinyshine.cricket.deploy.WebAppDeployHelper;
import org.destinyshine.cricket.server.AbstractLifecycle;
import org.destinyshine.cricket.server.LifecycleException;
import org.destinyshine.cricket.server.LifecycleState;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.JAXBException;
import java.io.FileNotFoundException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;

/**
 * Created by destinyliu on 2016/2/27.
 */
public class WebApplicationContainer extends AbstractLifecycle{

    private static final Logger logger = LogManager.getLogger();

    private WebApplicationContext root;

    private List<WebApplicationContext> webApplicationContexts = new LinkedList<>();

    private ExecutorService connectionExecutorService = new ThreadPoolExecutor(1, 100,
            2L, TimeUnit.MINUTES,
            new LinkedBlockingQueue<>());

//    private ConnectionReceiver connectionReceiver;

    private WebAppDeployHelper webAppDeployer;

    private String webappsBase;


    public WebApplicationContainer() {

    }

    public WebApplicationContext createContext(String contextPath, String webappDir) {
        WebApplicationContext webApplicationContext = null;
        try {
//            File dir = new File(webappDir);
            if (contextPath.equals("/") || contextPath.equals("")) {
                webApplicationContext = new WebApplicationContext(this, "", webappDir);
                this.root = webApplicationContext;
            } else {
                webApplicationContext = new WebApplicationContext(this, contextPath, webappDir);
                this.webApplicationContexts.add(webApplicationContext);
            }
        } catch (FileNotFoundException e) {
            logger.error(e.getMessage(), e);
            e.printStackTrace();
        } catch (JAXBException e) {
            logger.error(e.getMessage(), e);
        }

//        this.connectionReceiver = new ConnectionReceiver() {
//            @Override
//            public void recevieConnection(Connection connection) {
//                WebApplicationContainer.this.recevieConnection(connection);
//            }
//        };

        return webApplicationContext;
    }

    public void recevieConnection(Connection connection) {
        connectionExecutorService.submit(() -> {

            HttpServletRequest request = connection.getRequest();
            String requestURI = request.getRequestURI();
            WebApplicationContext dispatchedContext = null;
            for (WebApplicationContext context : webApplicationContexts) {
                String contextPath1 = context.getContextPath();
                if (requestURI.startsWith(contextPath1)) {
                    dispatchedContext = context;
                    break;
                }
            }
            if (dispatchedContext == null) {
                dispatchedContext = root;
            }

            dispatchedContext.recevieConnection(connection);

        });
    }

    public ClassLoader getContainerClassLoader() {
        return this.getClass().getClassLoader();
    }

    @Override
    protected void initInternal() throws LifecycleException {

    }

    @Override
    protected void startInternal() throws LifecycleException {
        setState(LifecycleState.STARTING);
        findContexts();

        logger.info("starting WebApplicationContainer.");
        this.root.start();
        for (WebApplicationContext webapp : webApplicationContexts) {
            webapp.start();
        }
    }

    @Override
    protected void stopInternal() throws LifecycleException {

    }

    @Override
    protected void destroyInternal() throws LifecycleException {

    }

    public void findContexts() {
       // webappsBase
    }
}
